home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Alles Voor Internet / Tout Pour Internet
/
alles voor internet.iso
/
MacInternet™
/
Telnet
/
NCSA
/
tn3270 2.4d7 source
/
tn3270
/
vmxfer.c
< prev
next >
Wrap
Text File
|
1992-04-17
|
36KB
|
1,483 lines
/*
* tn3270 for the Macintosh Source Code
* Brown University Computing and Information Services
* Version 2.4d7 April, 1992
* Copyright (c) 1988, 1989, 1990, 1991, 1992 by Brown University and by
* Peter John DiCamillo.
*
* Permission is granted to any individual or institution to use, copy,
* or redistribute the binary version of this software and its
* documentation provided this notice and the copyright notices are
* retained. Permission is granted to any individual or non-profit
* institution to use, copy, modify, or redistribute the source files
* of this software provided this notice and the copyright notices are
* retained. This software may not be distributed for profit, either
* in original form or in derivative works, nor can the source be
* distributed to other than an individual or a non-profit institution.
* Any individual or group interested in seeing and/or using these
* source files but who are prevented from doing so by the above
* constraints should contact Don Wolfe, Assistant Vice-President for
* Computer Systems at Brown University, (401) 863-7250, for possible
* software licensing of the source developed at Brown.
*
* Brown University and Peter John DiCamillo make no representations
* about the suitability of this software for any purpose.
*
* BROWN UNIVERSITY AND PETER JOHN DICAMILLO GIVE NO WARRANTY, EITHER
* EXPRESS OR IMPLIED, FOR THE PROGRAM AND/OR DOCUMENTATION PROVIDED,
* INCLUDING, WITHOUT LIMITATION, WARRANTY OF MERCHANTABILITY AND
* WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE.
*
*/
#if !defined(USEDUMP)
#include "maclib.h"
#include "termdef.h"
#include "tn3270funcs.h"
#include "globals.h"
#else
#pragma load "tn3270DumpFile"
#endif
#pragma segment vmxfer
#define IAC 255 /* Telnet: interpret as command: */
vmprt prtinfo = { /* defaults if VMPR 128 resource is not present */
4, /* fontnum */
10, /* pointsize */
12, /* leading */
132, /* linewidth */
4, /* tabsize */
57, /* pagelength */
59, /* pagelencc */
14, /* top */
2, /* headmarg */
12, /* left */
0, /* leftcc */
74, /* titlewidth */
0, 0, 0, 0}; /* unused fields */
extern struct Point sfppoint, sfgpoint;
void vmxfer(cnr *cp)
{
/* In xfer mode, the Mac program acts as a slave to VM/370,
executing each command from VM (a command may include data
to be processed) and returning a return code or data block. */
register short i; /* loop counter */
short rmax; /* count for uncompress loop */
unsigned char rchk[5]; /* received checksum string */
unsigned char cchk[5]; /* computed checksum string */
char cmdok; /* if true, command is ok */
/* process a command from VM */
cp->slen = 0;
if ((cp->rlen==2) && ((cp->rbuf)[0]==XFBGN) && ((cp->rbuf)[1]==XFBGN)) {
xfrst(cp);
cp->vmxbgn = 1; /* set xfer mode */
xfdlg(0, "", "", "", "", cp);
return;
}
if (!(cp->vmxbgn)) {
(cp->sbuf)[cp->slen++] = ' ';
return;
}
if ((cp->rlen==1) && ((cp->rbuf)[0]==DC4)) { /* subset code */
if (cp->vmxsub) {
if (cp->xdlg) SelectWindow(cp->xdlgptr);
}
else if (cp->myWindow != 0) SelectWindow(cp->myWindow);
cp->vmxsub ^= 1;
if (cp->myWindow != 0) newstat(cp);
return;
}
/* process compressed data */
if ((cp->rlen > 6) && ((cp->rbuf)[0] == 0x18)) {
memcpy(cp->sbuf, cp->rbuf+1, cp->rlen-1); /* copy data without prefix */
cp->cmpstate = 0;
rmax = cp->rlen-6; /* length without prefix or CRC */
cp->rlen = 0;
for (i=0; i < rmax; i++) datachr(&(cp->rlen), (cp->sbuf)[i], cp);
while(i < rmax+5) (cp->rbuf)[cp->rlen++] = (cp->sbuf)[i++]; /* append CRC */
}
/* verify data read is valid; if not, set cmdok FALSE */
if ((cp->rlen > 6) & (cp->rlen < 2320)) {
(cp->rbuf)[cp->rlen] = '\0'; /* delimit received checksum */
strcpy(rchk,cp->rbuf+cp->rlen-4); /* copy checksum */
(cp->rbuf)[cp->rlen-5] = '\0'; /* delimit data */
cp->rlen -= 5; /* rlen = data length */
chkdata(cp->rbuf, cp->rlen,cchk); /* calculate data checksum */
cmdok = (strcmp(rchk,cchk) == 0); /* compare checksums */
}
else cmdok = 0;
/* If command is ok, return the result of attempting to execute
it. If the command is in error, just transmit a blank. */
if (cmdok) {
cp->crcok = 0; /* no CRC yet */
excmmd(cp); /* execute command */
if (cp->crcok == 0) { /* append CRC if needed */
if (cp->slen == 0) cp->slen = strlen(cp->sbuf); /* get data length */
chkdata(cp->sbuf,cp->slen,cchk); /* get checksum */
(cp->sbuf)[cp->slen] = CD; /* delimit checksum */
memcpy(cp->sbuf+cp->slen+1, cchk, 4); /* append checksum */
cp->slen += 5; /* update length */
}
}
else (cp->sbuf)[cp->slen++] = ' ';
}
void chkdata(unsigned char *buf, short len, unsigned char *chk)
{
register unsigned char i;
/* calculate four-byte ASCII checksum for buf in chk */
sprintf(chk,"%4x",crcf(buf,len,0));
for (i = 0; i < 4; i++) /* convert blanks to zeros */
if (chk[i] == ' ') chk[i] = '0';
else chk[i] = toupper(chk[i]);
}
void excmmd(cnr *cp)
{
register unsigned short i;
i = ((cp->rbuf)[0] << 8) + (cp->rbuf)[1];
switch(i) {
case 0x4f49: /* 'OI' */
rdopen(cp);
break;
case 0x4249: /* 'BI' */
rdopen(cp);
break;
case 0x5242: /* 'RB' */
rdblock(cp);
break;
case 0x4349: /* 'CI' */
rdclose(cp);
break;
case 0x4f4f: /* 'OO' ASCII Output (old WMAC) */
case 0x414f: /* 'AO' Alternate Output (new WMAC) */
case 0x424f: /* 'BO' Binary Output (new WMAC) */
case 0x4d4f: /* 'MO' MacBinary Output (new WMAC) */
case 0x4d48: /* 'MH' MacBinary Header (new WMAC) */
wropen(cp);
break;
case 0x5742: /* 'WB' */
wrblock(cp);
break;
case 0x434f: /* 'CO' */
wrclose(cp);
break;
case 0x4558: /* 'EX' */
exitcmd(cp);
break;
case 0x5652: /* 'VR' */
verscmd(cp);
break;
case 0x5454: /* 'TT' */
trtime(cp);
break;
case 0x584c: /* 'XL' */
xlcmd(cp);
break;
default:
setrc(28, cp);
break;
}
}
void setrc(short code, cnr *cp)
{
register char i;
sprintf(cp->sbuf,"RC%4d",code);
for (i = 2; i < 6; i++)
if ((cp->sbuf)[i] == ' ') (cp->sbuf)[i] = '0';
}
void rdopen(cnr *cp)
{
short rdlast;
register short rc;
register char nomenu, rdcancel;
long fsize;
struct DateTimeRec fdate;
rdcancel = 0;
nomenu = 0; /* handle menu option */
rdlast = strlen(cp->rbuf+2) + 1;
if ((cp->rbuf)[rdlast] == '*') {
(cp->rbuf)[rdlast] = 0;
nomenu = 1;
}
cp->binxf = ((cp->rbuf)[0] == 'B');
rc = -1; /* simulate open error for menu */
cp->ropen = 0;
if (nomenu) {
strcpy(cp->macVName+1,currvname(cp)); /* get default volume */
(cp->macVName)[0] = strlen(cp->macVName+1);
strcpy(cp->macFName+1,cp->rbuf+2); /* get file id */
(cp->macFName)[0] = strlen(cp->macFName+1);
rc = fsrdopen(cp->macFName+1, cp->vnum, &(cp->rfd));
}
if (rc != 0) { /* get id from user */
getrd(cp->macFName, cp);
if ((cp->macFName)[0] == 0) rdcancel = 1;
if (!rdcancel)
rc = fsrdopen(cp->macFName+1, cp->vnum, &(cp->rfd));
}
if (rc != 0) {
if (!rdcancel) stoperr(300, cp);
setrc(1, cp);
return;
}
if (rc == 0) cp->ropen = 1;
strcpy(cp->statname,"Uploading");
getinfo(&fsize, &fdate, cp);
cp->filsiz = (fsize + 127) >> 7;
cp->cursiz = 0;
strcpy(cp->sbuf,"AT"); /* success: return file attributes */
if (cp->binxf) (cp->sbuf)[0] = 'B'; /* use BT for binary transfer */
sprintf(cp->sbuf+2,"%04x",cp->filsiz); /* file size */
sprintf(cp->sbuf+6,"%04d%02d%02d%02d%02d%02d", /* date */
fdate.year,fdate.month,fdate.day,fdate.hour,
fdate.minute,fdate.second);
}
void rdclose(cnr *cp)
{
cp->ropen = 0;
if (FSClose(cp->rfd) != 0) setrc(1, cp); /* close input file */
else {
FlushVol(0L, cp->vnum);
setrc(0, cp);
}
}
void rdblock(cnr *cp)
{
short rc, rdlen, padlen;
register short i, reccnt;
unsigned char blkstr[5];
char eof, trflg;
unsigned char padchr;
register unsigned char c, maxchar;
unsigned long recnum, r_byte;
short iaccount, dest, src;
unsigned char cchk[5]; /* computed checksum string */
if (cp->kabort) { /* set rc 11 for subset/abort */
setrc(11, cp);
cp->kabort = 0;
return;
}
/* give error 3 if block number and speed not read */
if (cp->rlen < 10) {
setrc(3, cp);
return;
}
/* extract xfspeed and save */
memcpy(blkstr, cp->rbuf+6, 4);
blkstr[4] = '\0';
cp->xfspeed = atoi(blkstr);
/* extract block number and convert to record */
memcpy(blkstr, cp->rbuf+2, 4);
blkstr[4] = '\0';
recnum = atol(blkstr); /* record = block * 18 */
recnum *= 18;
/* read 18 records (2304 bytes) or less at end of file */
strcpy(cp->sbuf,"DB"); /* store data block prefix */
typstat(cp);
r_byte = recnum << 7; /* byte offset = record * 128 */
rc = SetFPos(cp->rfd, 1, r_byte); /* position for read */
if (rc == eofErr) { /* rc 1 for eof */
setrc(1, cp);
return;
}
else if (rc != 0) {
stoperr(301, cp);
setrc(8, cp);
return;
}
r_byte = 2304; /* read next 2304 bytes of data */
rc = FSRead(cp->rfd, (long *)&r_byte, cp->sbuf+2);
if ((rc != eofErr) && (rc != 0)) { /* check for errors */
stoperr(301, cp);
setrc(9, cp);
return;
}
if (r_byte == 0) { /* assume eof if zero bytes read */
setrc(1, cp);
return;
}
rdlen = r_byte;
padlen = 128 - (rdlen % 128); /* pad to a multiple of 128 */
if (cp->binxf) padchr = 0;
else padchr = CPMEOF;
if (padlen < 128) {
rdlen += 2;
for (i=0; i < padlen; i++) (cp->sbuf)[rdlen++] = padchr;
rdlen -= 2;
}
if (cp->binxf) cp->slen = rdlen+2;
else (cp->sbuf)[rdlen+2] = '\0';
reccnt = rdlen >> 7; /* no. of 128-byte blocks */
if (reccnt > 0) cp->cursiz = recnum + reccnt;
/* For TCP/IP binary transfer, quoting must be inserted for the IAC
character (X'FF') by replacing each IAC by two of them */
if (cp->binxf && cp->tcpflg) {
/* append CRC before changing data */
chkdata(cp->sbuf,cp->slen,cchk); /* get checksum */
(cp->sbuf)[cp->slen] = CD; /* delimit checksum */
memcpy(cp->sbuf+cp->slen+1, cchk, 4); /* append checksum */
cp->slen += 5; /* update length */
cp->crcok = 1; /* tell mainline CRC done */
/* now handle IAC characters */
iaccount = 0;
for (i=2; i < cp->slen; i++) {
if ((cp->sbuf)[i] == IAC) iaccount++;
}
if (iaccount == 0) return;
dest = cp->slen + iaccount - 1;
src = cp->slen - 1;
cp->slen += iaccount;
while (iaccount > 0) {
(cp->sbuf)[dest--] = c = (cp->sbuf)[src--];
if (c == IAC) {
(cp->sbuf)[dest--] = IAC;
iaccount--;
}
}
return;
}
if (cp->binxf) return;
/* translate invalid characters to "|" and display file
data on terminal */
eof = trflg = 0;
rdlen += 2;
/* versions of RMAC/WMAC which issue the XL command also support Macintosh
extended ASCII, and can translate characters through X'DE' */
if (cp->xlflag) maxchar = 222;
else maxchar = 126;
for (i = 2; i < rdlen; i++) {
if (eof) {
(cp->sbuf)[i] = '\0';
break;
}
c = (cp->sbuf)[i];
switch (c) {
case TAB:
case LF:
case FF:
break;
case CR:
(cp->sbuf)[i] = VT;
break;
case CPMEOF:
eof = 1;
break;
case DEL:
trflg = 1;
(cp->sbuf)[i] = '|';
break;
default:
if ((c < 32) || (c > maxchar)) {
trflg = 1;
(cp->sbuf)[i] = '|';
}
break;
}
}
if (trflg) stoperr(302, cp);
}
void typstat(cnr *cp) /* output transfer status */
{
unsigned char tofrom[5];
unsigned percent, min, sec, ovrhead;
long lcvt, lchar, curbytes, totbytes;
curbytes = (long)(cp->cursiz) << 7;
totbytes = (long)(cp->filsiz) << 7;
lcvt = cp->cursiz;
percent = (lcvt*100)/cp->filsiz;
if (cp->prtxf) {
sprintf(cp->statbuf, "%s '%s'", cp->statname, cp->macFName+1);
}
else {
if ((cp->statname)[0] == 'D') strcpy(tofrom,"to");
else strcpy(tofrom,"from");
sprintf(cp->statbuf,"%s '%s' %s '%s'", cp->statname, cp->macFName+1,
tofrom, cp->macVName+1);
}
sprintf(cp->prtbuf2,"%ld/%ld (%d%%)", curbytes, totbytes, percent);
if (cp->xfspeed == 0) {
sprintf(cp->prtbuf3,"");
sprintf(cp->prtbuf4,"??:??");
}
else {
ovrhead = (cp->filsiz-cp->cursiz+7)/8; /* no. of rb/wb cmmds. */
if ((cp->statname)[0] == 'D') ovrhead *= 30;
else ovrhead *= 26;
lchar = cp->filsiz - cp->cursiz; /* get total character count */
lchar <<= 7;
lchar += ovrhead; /* plus overhead */
lcvt = cp->xfspeed;
sec = lchar/lcvt; /* get seconds */
min = sec / 60;
sec = sec % 60;
sprintf(cp->prtbuf3,"%d",cp->xfspeed);
sprintf(cp->prtbuf4,"%d:%02d",
min,sec);
}
xfdlg(1,cp->statbuf,cp->prtbuf2,cp->prtbuf3,cp->prtbuf4, cp);
}
void wropen(cnr *cp)
{
unsigned char cvtbuff[5];
short rdlast;
register short rc;
unsigned short i;
register unsigned long freeBytes, totBytes;
VolumeParam pb;
struct DateTimeRec fdate;
int year, month, day, hour, minute, second;
char mhcmd;
HFileParam pbf;
GrafPtr gp;
static unsigned char listingft1[] = "listing";
static unsigned char listingft2[] = "LISTING";
static long minus1 = -1;
mhcmd = ((cp->rbuf)[0] == 'M') && ((cp->rbuf)[1] == 'H');
if (mhcmd) {
memcpy(&(cp->mh), cp->rbuf+2, 128); /* save header */
if ((cp->mh.fnlen == 0) || (cp->mh.fnlen > 63)) {
stoperr(303, cp);
setrc(64, cp); /* check for valid fn length */
return;
}
p2cstr(&(cp->mh.fnlen)); /* convert filename to C format */
cp->mbdsize = chartolong(cp->mh.dataln); /* get lengths of forks */
cp->mbrsize = chartolong(cp->mh.rscln);
cp->mbdbmax = (cp->mbdsize+127) >> 7; /* get block counts */
cp->mbrbmax = (cp->mbrsize+127) >> 7;
cp->mbdextra = (cp->mbdbmax << 7) - cp->mbdsize; /* get padding counts */
cp->mbrextra = (cp->mbrbmax << 7) - cp->mbrsize;
}
else { /* if not MH, get info. from rbuf */
/* set nomenu or prtxf flag */
cp->nomenu = 0;
cp->prtxf = 0;
rdlast = strlen(cp->rbuf+20) + 19;
if ((cp->rbuf)[rdlast] == '*') {
(cp->rbuf)[rdlast] = 0;
cp->nomenu = 1;
}
else if ((cp->rbuf)[rdlast] == '.') {
(cp->rbuf)[rdlast] = 0;
cp->prtxf = 1;
}
/* get file size */
memcpy(cvtbuff, cp->rbuf+2, 4);
cvtbuff[4] = '\0';
sscanf(cvtbuff, "%x", &(cp->filsiz));
/* get file date and time */
sscanf(cp->rbuf+6, "%4d%2d%2d%2d%2d%2d",
&year, &month, &day, &hour,
&minute, &second);
fdate.year = year;
fdate.month = month;
fdate.day = day;
fdate.hour = hour;
fdate.minute = minute;
fdate.second = second;
fdate.dayOfWeek = 0;
cp->wdate = fdate;
}
if (((cp->rbuf)[0] == 'M') && ((cp->rbuf)[1] == 'O')) {
/* finish MO processing */
cp->binxf = cp->mbinxf = 1;
cp->prtxf = 0;
strcpy(cp->sbuf,"MT");
return;
}
/* set binxf, mbinxf for all but "MO" */
if ((cp->rbuf)[1] == 'O') {
cp->binxf = ((cp->rbuf)[0] == 'B');
cp->mbinxf = 0;
}
/* get file id to use */
if (!(cp->prtxf)) {
if (cp->nomenu) {
strcpy(cp->macVName+1, currvname(cp));
(cp->macVName)[0] = strlen(cp->macVName+1);
if (mhcmd) strcpy(cp->macFName+1, &(cp->mh.fnlen));
else strcpy(cp->macFName+1,cp->rbuf+20);
(cp->macFName)[0] = strlen(cp->macFName+1);
/* check if file already exists */
c2pstr(cp->macFName+1);
rc = FSOpen(cp->macFName+1, cp->vnum, &(cp->wfd));
p2cstr(cp->macFName+1);
if (rc == 0) {
setrc(1, cp);
FSClose(cp->wfd);
FlushVol(0L, cp->vnum);
return;
}
}
else if (mhcmd) getwr(&(cp->mh.fnlen), cp->macFName, cp);
else getwr(cp->rbuf+20, cp->macFName, cp);
if (strlen(cp->macFName) == 0) {
setrc(5, cp);
return;
}
}
else {
strcpy(cp->macFName+1, cp->rbuf+20);
(cp->macFName)[0] = strlen(cp->macFName+1);
i = (cp->macFName)[0] - strlen(listingft1);
if (i >= 2)
cp->prtcc = (strcmp(listingft1, cp->macFName+i+1) == 0) ||
(strcmp(listingft2, cp->macFName+i+1) == 0);
else
cp->prtcc = 0;
prtwrite(&minus1, 0L, cp); /* prtwrite initialization */
}
/* now ready to use file id */
if (!(cp->prtxf)) {
/* initialize for file calls */
memset(&pbf, 0, sizeof(HFileParam));
/* delete any existing file */
pbf.ioNamePtr = (StringPtr)(cp->macFName);
pbf.ioVRefNum = cp->vnum;
PBDelete((ParmBlkPtr)&pbf, 0);
/* create new file */
rc = PBCreate((ParmBlkPtr)&pbf, 0);
if (rc != 0) {
stoperr(303, cp);
setrc(2, cp);
return;
}
/* set finder info */
rc = PBGetFInfo((ParmBlkPtr)&pbf, 0);
if (rc != 0) {
stoperr(303, cp);
setrc(2, cp);
return;
}
/* set finder flags */
if (cp->mbinxf) {
i = cp->mh.flags;
i <<= 8;
pbf.ioFlFndrInfo.fdFlags &= 0x00ff;
pbf.ioFlFndrInfo.fdFlags |= i;
pbf.ioFlFndrInfo.fdFlags &= 0xf8ff;
}
else pbf.ioFlFndrInfo.fdFlags &= 0xfeff;
/* set type and creator */
if (cp->mbinxf) {
memcpy(&pbf.ioFlFndrInfo.fdType, cp->mh.ftyp, 4);
memcpy(&pbf.ioFlFndrInfo.fdCreator, cp->mh.fcreat, 4);
}
else {
pbf.ioFlFndrInfo.fdType = 'TEXT';
pbf.ioFlFndrInfo.fdCreator = cp->cs.text_creator;
}
rc = PBSetFInfo((ParmBlkPtr)&pbf, 0);
if (rc != 0) {
stoperr(303, cp);
setrc(2, cp);
return;
}
/* open data fork */
memset(&pbf, 0, sizeof(HFileParam));
pbf.ioNamePtr = (StringPtr)(cp->macFName);
pbf.ioVRefNum = cp->vnum;
pbf.filler1 = fsWrPerm; /* ioPermssn */
rc = PBOpen((ParmBlkPtr)&pbf, 0);
if (rc != 0) {
stoperr(303, cp);
setrc(2, cp);
return;
}
else cp->wfd = pbf.ioFRefNum;
/* open resource fork if MacBinary */
if (cp->mbinxf) {
rc = PBOpenRF((ParmBlkPtr)&pbf, 0);
if (rc != 0) {
stoperr(303, cp);
setrc(2, cp);
return;
}
else cp->wfd_r = pbf.ioFRefNum;
}
}
else {
if (hPrint == 0) {
stoperr(305, cp);
setrc(2, cp);
return;
}
arrowcursor();
if (prtinit == 0) {
PrOpen();
PrintDefault(hPrint);
prtinit = 1;
}
if (!PrJobDialog(hPrint)) {
setrc(5, cp);
return;
}
cp->myFirst = (*hPrint)->prJob.iFstPage;
cp->myLast = (*hPrint)->prJob.iLstPage;
(*hPrint)->prJob.iFstPage = 1;
(*hPrint)->prJob.iLstPage = 999;
if (cp->myFirst < 1) cp->myFirst = 1;
if (cp->myLast < cp->myFirst) cp->myLast = 999;
GetPort(&gp);
setdoctitle(cp->macFName+1);
cp->prtport = PrOpenDoc(hPrint, 0L, 0L);
SetPort(gp);
cp->prdocopen = 1; /* document now open */
}
cp->wopen = 1;
if (cp->binxf && (!(cp->mbinxf))) strcpy(cp->sbuf,"BT");
else setrc(0, cp);
if (cp->prtxf) strcpy(cp->statname, "Printing");
else strcpy(cp->statname,"Downloading");
if (!(cp->prtxf)) {
pb.ioCompletion = 0;
pb.ioNamePtr = 0;
pb.ioVRefNum = cp->vnum;
pb.ioVolIndex = 0;
PBGetVInfo((ParmBlkPtr)&pb, 0);
freeBytes = pb.ioVFrBlk * pb.ioVAlBlkSiz;
totBytes = (long)(cp->filsiz) << 7;
if (freeBytes < totBytes) {
totBytes = (totBytes - freeBytes + 1023) >> 10;
dFullAlt((short)totBytes, cp);
FSClose(cp->wfd);
if (cp->mbinxf) FSClose(cp->wfd_r);
c2pstr(cp->macFName+1);
FSDelete(cp->macFName+1, cp->vnum);
p2cstr(cp->macFName+1);
setrc(99, cp);
return;
}
}
cp->cursiz = 0;
typstat(cp);
}
void wrclose(cnr *cp)
{
short rc1, rc2;
cp->wopen = 0;
if (!(cp->prtxf)) {
rc1 = FSClose(cp->wfd);
if (cp->mbinxf) rc2 = FSClose(cp->wfd_r);
else rc2 = 0;
if ((rc1 != 0) || (rc2 != 0)) {
FlushVol(0L, cp->vnum);
stoperr(304, cp);
setrc(1, cp);
}
else {
rc1 = settime(&(cp->wdate), &(cp->mh), cp);
setrc(rc1, cp);
FlushVol(0L, cp->vnum);
}
}
else setrc(xfprtclose(cp), cp);
}
int xfprtclose(cnr *cp)
{
int rc;
TPrStatus prStatus;
static long minus3 = -3;
GrafPtr gp;
prtwrite(&minus3, 0L, cp); /* termination call */
GetPort(&gp);
if (cp->prpgopen) {
SetPort((GrafPtr)(cp->prtport));
PrClosePage(cp->prtport);
}
if (cp->prdocopen) {
SetPort((GrafPtr)(cp->prtport));
PrCloseDoc(cp->prtport);
if (((*hPrint)->prJob.bJDocLoop == bSpoolLoop) && (PrError() == noErr))
PrPicFile(hPrint, 0L, 0L, 0L, &prStatus);
if (PrError() != noErr) {
stoperr(305, cp);
rc = 1;
}
else rc = 0;
}
else rc = 0;
SetPort(gp);
cp->prtxf = cp->prpgopen = cp->prdocopen = cp->prfileinit = 0;
return(rc);
}
void wrblock(cnr *cp)
{
register short i, reccnt;
register short padlen;
short typlen, bufwrite();
unsigned char blkstr[5], c;
unsigned long recnum, w_byte;
OSErr rc;
if (cp->kabort) { /* set rc 11 for subset/abort */
setrc(11, cp);
cp->kabort = 0;
return;
}
/* rbuf should contain: WBnnnnssssxxxx..., where "nnnn" is
the block number, "ssss" is the transfer speed in cps,
and "xxxx..." is the data to write. */
/* give error 3 if block number and speed not read */
if (cp->rlen < 10) {
setrc(3, cp);
return;
}
/* translate SO, VT to CR, LF */
typlen = cp->rlen - 10;
if (!(cp->binxf)) for (i=0; i < typlen; i++) {
c = (cp->rbuf)[i+10];
switch (c) {
case CPMEOF: /* ignore EOF char */
break;
case SO: /* SO is translated CR */
(cp->rbuf)[i+10] = CR;
break;
case VT: /* VT is translated LF */
(cp->rbuf)[i+10] = LF;
break;
case FF:
break;
default:
break;
}
}
/* extract xfspeed and save */
memcpy(blkstr, cp->rbuf+6, 4);
blkstr[4] = '\0';
cp->xfspeed = atoi(blkstr);
/* extract block number and convert to record */
memcpy(blkstr, cp->rbuf+2, 4);
blkstr[4] = '\0';
recnum = atol(blkstr); /* record = block * 18 */
recnum *= 18;
/* assume eof if < 2304 bytes to write; pad with EOF char
to make a multiple of 128 bytes */
padlen = 128 - ((cp->rlen-10) % 128);
if (cp->binxf) {
if (padlen < 128) reccnt = (padlen+cp->rlen-10) >> 7;
else reccnt = (cp->rlen-10) >> 7;
}
else {
if (padlen < 128)
for (i=0; i < padlen; i++) (cp->rbuf)[cp->rlen++] = CPMEOF;
reccnt = (cp->rlen-10) >> 7; /* divide by 128 to get block count */
}
/* return now if no blocks to write (should only happen at eof) */
if (reccnt == 0) {
setrc(0, cp);
return;
}
/* for a text file, delete trailing EOF characters */
if (!(cp->binxf)) {
cp->rlen--; /* convert length to rbuf offset */
while (cp->rlen >= 10) {
if ((cp->rbuf)[cp->rlen] != CPMEOF) break;
cp->rlen--;
}
cp->rlen++; /* convert back to length */
if (cp->rlen == 10) { /* return if only EOF characters */
setrc(0, cp);
return;
}
}
/* write data to disk. give return code 4 for an error */
if ((!(cp->mbinxf)) && (!(cp->prtxf))) {
w_byte = recnum << 7; /* get byte offset */
rc = SetFPos(cp->wfd, 1, w_byte);
if (rc != 0) {
stoperr(304, cp);
setrc(4, cp);
return;
}
}
w_byte = cp->rlen-10;
if (cp->mbinxf) rc = mbwrite((long *)&w_byte, cp->rbuf+10, recnum, cp);
else if (cp->prtxf) rc = prtwrite((long *)&w_byte, cp->rbuf+10, cp);
else rc = FSWrite(cp->wfd, (long *)&w_byte, cp->rbuf+10);
if ((rc != 0) || (w_byte != cp->rlen-10)) {
if (cp->prtxf) stoperr(305, cp);
else stoperr(304, cp);
setrc(5, cp);
return;
}
setrc(0, cp);
cp->cursiz = recnum + reccnt;
typstat(cp);
}
void exitcmd(cnr *cp) /* exit command */
{
setrc(0, cp);
xfrst(cp);
}
void verscmd(cnr *cp) /* return version info */
{
strcpy(cp->sbuf,"VIM0231"); /* Macintosh 3270 version 2.31 */
/* append national language name */
strcat(cp->sbuf, ":");
strcat(cp->sbuf, cp->csnlname);
}
void xlcmd(cnr *cp) /* return national language translation info. */
{
unsigned char *sptr;
register short i, x, j;
cp->xlflag = 1;
strcpy(cp->sbuf, "XI"); /* translation info */
sptr = cp->sbuf+2;
if (cp->nl_handle != 0) {
for (i=0; i < 256; i++) {
x = (cp->nltab)[i];
if (x != i) {
sprintf(sptr, "%02x%02x", i, x);
for (j=0; j < 4; j++) {
sptr[j] = toupper(sptr[j]);
}
sptr += 4;
}
}
}
}
void trtime(cnr *cp) /* read and display new transfer time */
{
unsigned char blkstr[5];
/* extract xfspeed and save */
memcpy(blkstr, cp->rbuf+2, 4);
blkstr[4] = '\0';
cp->xfspeed = atoi(blkstr);
/* display new status */
typstat(cp);
/* return normal rc */
setrc(0, cp);
}
void getrd(unsigned char *macname, cnr *cp)
{
Point where;
pascal Boolean (*fileFilter) ();
register short numTypes;
SFTypeList typeList;
DlgHookProcPtr dlgHook;
SFReply reply;
VolumeParam pbrec;
register VolumeParam * _pbrec;
_pbrec = &pbrec;
where = sfgpoint;
dlgHook = 0;
fileFilter = onlydata;
numTypes = -1;
arrowcursor();
SFGetFile(where, "\p", fileFilter, numTypes,
typeList, dlgHook, &reply);
macname[0] = macname[1] = '\0';
if (reply.good == 0) return;
macname[0] = reply.fName[0];
strcpy(macname+1, p2cstr(&reply.fName));
cp->vnum = reply.vRefNum;
pbrec.ioCompletion = 0;
pbrec.ioVRefNum = cp->vnum;
pbrec.ioVolIndex = 0;
pbrec.ioNamePtr = (StringPtr)(cp->macVName);
PBGetVInfo((ParmBlkPtr)_pbrec, 0);
(cp->macVName)[1+(cp->macVName)[0]] = '\0';
}
pascal Boolean onlydata(FileParam *_pb)
{
if (_pb->ioFlLgLen == 0L) return(0x100);
else return(0);
}
void getwr(unsigned char *suggid, unsigned char *macname, cnr *cp)
{
Point where;
DlgHookProcPtr dlgHook;
SFReply reply;
VolumeParam pbrec;
VolumeParam * _pbrec;
_pbrec = &pbrec;
where = sfppoint;
dlgHook = 0;
arrowcursor();
c2pstr(suggid);
SFPutFile(where, "\pSave downloaded file as:",
suggid, dlgHook, &reply);
p2cstr(suggid);
macname[0] = macname[1] = '\0';
if (reply.good == 0) return;
macname[0] = reply.fName[0];
strcpy(macname+1, p2cstr(&reply.fName));
cp->vnum = reply.vRefNum;
pbrec.ioCompletion = 0;
pbrec.ioVRefNum = cp->vnum;
pbrec.ioVolIndex = 0;
pbrec.ioNamePtr = (StringPtr)cp->macVName;
PBGetVInfo((ParmBlkPtr)_pbrec, 0);
(cp->macVName)[1+(cp->macVName)[0]] = '\0';
}
unsigned char *currvname(cnr *cp)
{
VolumeParam pb;
OSErr rc;
pb.ioCompletion = 0;
pb.ioNamePtr = (StringPtr)(cp->rtnvol);
pb.ioVRefNum = cp->vnum;
pb.ioVolIndex = 0;
rc = PBGetVInfo((ParmBlkPtr)&pb, 0);
if (rc == 0) p2cstr(cp->rtnvol);
else {
GetVol(cp->rtnvol, &(cp->vnum));
p2cstr(cp->rtnvol);
}
return(cp->rtnvol);
}
void getinfo(long *fsize, struct DateTimeRec *fdate, cnr *cp)
{
FileParam fblk;
register FileParam * _fblk;
_fblk = &fblk;
fblk.ioCompletion = 0;
fblk.ioNamePtr = (StringPtr)(cp->macFName);
fblk.ioVRefNum = cp->vnum;
fblk.ioFVersNum = 0;
fblk.ioFDirIndex = 0;
PBGetFInfo((ParmBlkPtr)_fblk,0);
*fsize = fblk.ioFlLgLen;
Secs2Date(fblk.ioFlMdDat, fdate);
}
OSErr settime(struct DateTimeRec *fdate, struct mbhdr *mh, cnr *cp)
{
FileParam fblk;
long crsecs, mdsecs;
OSErr rc;
memset(&fblk, 0, sizeof(FileParam));
fblk.ioNamePtr = (StringPtr)(cp->macFName);
fblk.ioVRefNum = cp->vnum;
rc = PBGetFInfo((ParmBlkPtr)&fblk,0);
if (rc != 0) return(rc+200);
Date2Secs(fdate, &fblk.ioFlMdDat);
Date2Secs(fdate, &fblk.ioFlCrDat);
if (cp->mbinxf) {
crsecs = chartolong(mh->crdate);
mdsecs = chartolong(mh->mddate);
if ((crsecs != 0) && (mdsecs != 0)) {
fblk.ioFlMdDat = mdsecs;
fblk.ioFlCrDat = crsecs;
}
}
rc = PBSetFInfo((ParmBlkPtr)&fblk,0);
if (rc != 0) return(rc+300);
else return(0);
}
void xfrst(cnr *cp)
{
short rc;
if (cp->prtxf) xfprtclose(cp);
else {
if (cp->ropen) if (FSClose(cp->rfd) == 0) FlushVol(0L, cp->vnum);
if (cp->wopen) {
rc = FSClose(cp->wfd);
if ((rc == 0) && cp->mbinxf) rc = FSClose(cp->wfd_r);
if (rc == 0) FlushVol(0L, cp->vnum);
}
}
xfdlg(2, "", "", "", "", cp);
xfinit(cp);
}
void xfinit(cnr *cp)
{
cp->vmxsub = cp->vmxbgn = 0;
cp->kabort = 0;
cp->ropen = cp->wopen = 0;
cp->xfspeed = 0;
cp->xdlg = 0;
cp->prtxf = 0;
cp->prdocopen = 0;
cp->prpgopen = 0;
cp->prfileinit = 0;
cp->xlflag = 0;
if (cp->myWindow != 0) {
newstat(cp);
}
}
void datachr(short *rdoff, unsigned char c, cnr *cp)
{
short count, max;
switch(cp->cmpstate) {
case 0: /* normal character */
if (c == 0x18) cp->cmpstate = 1;
else {
(cp->rbuf)[(*rdoff)++] = c;
cp->prevchar = c;
}
break;
case 1: /* after x'18' */
if (c == 0x18) { /* literal x'18' */
(cp->rbuf)[(*rdoff)++] = c;
cp->prevchar = c;
}
else { /* compression count */
count = (c - 0x20) + 2;
max = 2320 - (*rdoff);
if (count > max) count = max;
while (count > 0) {
(cp->rbuf)[(*rdoff)++] = cp->prevchar;
count--;
}
}
cp->cmpstate = 0;
break;
default:
break;
}
}
long chartolong(unsigned char *str)
{
union {
unsigned char s[4];
long l;
} u;
memcpy(u.s, str, 4);
return(u.l);
}
OSErr mbwrite(long *count, unsigned char *data, unsigned long offset, cnr *cp)
{
long bcnt, tsize, wsize;
OSErr rc;
unsigned char * newdata;
long newcount;
long mbdbcnt, mbrbcnt, mbtotal;
long pos;
/* set block counts file block offset */
mbtotal = cp->mbdbmax + cp->mbrbmax;
if (offset > mbtotal) return(999);
if ((offset == mbtotal) && ((*count) != 0)) return(998);
if (offset >= cp->mbdbmax) {
mbdbcnt = 0;
mbrbcnt = mbtotal - offset;
}
else {
mbdbcnt = cp->mbdbmax - offset;
mbrbcnt = cp->mbrbmax;
}
bcnt = ((*count) + 127) >> 7;
if (bcnt > (mbdbcnt + mbrbcnt)) bcnt = mbdbcnt + mbrbcnt;
if (bcnt == 0) return(0);
newdata = data; /* init. data for resource fork */
newcount = (*count);
if (mbdbcnt > 0) {
if (bcnt <= mbdbcnt) { /* all blocks in data fork */
wsize = bcnt << 7;
if (bcnt == mbdbcnt) wsize -= cp->mbdextra;
tsize = wsize;
if (wsize <= (*count)) {
pos = (cp->mbdbmax - mbdbcnt) << 7;
rc = SetFPos(cp->wfd, 1, pos);
if (rc == 0) rc = FSWrite(cp->wfd, &wsize, data);
}
else rc = -999;
if ((rc == 0) && (wsize == tsize)) return(0);
else {
(*count) = 0;
return(rc);
}
}
else { /* blocks for resource fork too */
wsize = mbdbcnt << 7;
newdata = data + wsize;
newcount = (*count) - wsize;
wsize -= cp->mbdextra;
tsize = wsize;
pos = (cp->mbdbmax - mbdbcnt) << 7;
rc = SetFPos(cp->wfd, 1, pos);
if (rc == 0) rc = FSWrite(cp->wfd, &wsize, data);
if ((rc == 0) && (wsize == tsize)) bcnt -= mbdbcnt;
else {
(*count) = 0;
return(rc);
}
}
}
/* all remaining blocks for resource fork */
wsize = bcnt << 7;
if (bcnt == mbrbcnt) wsize -= cp->mbrextra;
tsize = wsize;
if (wsize <= newcount) {
pos = (cp->mbrbmax - mbrbcnt) << 7;
rc = SetFPos(cp->wfd_r, 1, pos);
if (rc == 0) rc = FSWrite(cp->wfd_r, &wsize, newdata);
}
else rc = -999;
if ((rc == 0) && (wsize == tsize)) {
mbrbcnt -= bcnt;
return(0);
}
else {
(*count) = 0;
return(rc);
}
}
OSErr prtwrite(long *count, unsigned char *addr, cnr *cp)
{
static long minus1 = -1;
static long minus2 = -2;
static long minus3 = -3;
unsigned short c, i, j;
if (((*count) == 0) || ((*count) < -3)) return(0);
if (((*count) == -1) || ((*count) == -2)) { /* initialization calls */
memset(cp->newline1, ' ', MAXLINEWIDTH+2); /* -1 for new page */
memset(cp->newline2, ' ', MAXLINEWIDTH+2); /* -2 for new line */
if (cp->prtcc) cp->prtlen = cp->prtlen1 = cp->prtlen2 = 0;
else cp->prtlen = cp->prtlen1 = cp->prtlen2 = 1;
if ((*count) == -1) cp->nextcc = '1';
else cp->nextcc = ' ';
return(0);
}
if ((*count) == -3) { /* termination call */
if (cp->prtcc) {
if (cp->prtlen1 > 0) {
(cp->newline1)[cp->prtlen1] = 0;
prtline(cp->newline1, cp);
}
}
else {
if (cp->prtlen1 > 1) {
(cp->newline1)[0] = cp->nextcc;
cp->nextcc = '+';
(cp->newline1)[cp->prtlen1] = 0;
prtline(cp->newline1, cp);
}
if (cp->prtlen2 > 1) {
(cp->newline2)[0] = cp->nextcc;
cp->nextcc = '+';
(cp->newline2)[cp->prtlen2] = 0;
prtline(cp->newline2, cp);
}
}
return(0);
}
for (i = 0; i < (*count); i++) {
c = addr[i];
if (cp->prtcc)
switch(c) {
case TAB:
if (cp->prtlen1 < prtinfo.linewidth+1) cp->prtlen1++;
while ((((cp->prtlen1-1) % prtinfo.tabsize) != 0) &&
((cp->prtlen1-1) < prtinfo.linewidth+1))
cp->prtlen1++;
break;
case CR:
if (cp->prtlen1 == 0) (cp->newline1)[cp->prtlen1++] = ' ';
prtwrite(&minus3, 0L, cp);
prtwrite(&minus2, 0L, cp);
break;
default:
if (cp->prtlen1 < prtinfo.linewidth+1)
(cp->newline1)[cp->prtlen1++] = c;
break;
}
else
switch (c) {
case BS:
if (cp->prtlen > 1) cp->prtlen--;
break;
case CR:
if ((cp->prtlen1 == 1) && (cp->prtlen2 == 1))
(cp->newline1)[cp->prtlen1++] = ' ';
prtwrite(&minus3, 0L, cp);
prtwrite(&minus2, 0L, cp);
break;
case LF:
j = cp->prtlen;
if ((cp->prtlen1 == 1) && (cp->prtlen2 == 1))
(cp->newline1)[cp->prtlen1++] = ' ';
prtwrite(&minus3, 0L, cp);
prtwrite(&minus2, 0L, cp);
cp->prtlen = j;
break;
case FF:
prtwrite(&minus3, 0L, cp);
prtwrite(&minus1, 0L, cp);
cp->prtlen1 = 2;
break;
case TAB:
if (cp->prtlen < prtinfo.linewidth+1) cp->prtlen++;
while ((((cp->prtlen-1) % prtinfo.tabsize) != 0) &&
((cp->prtlen-1) < prtinfo.linewidth+1))
cp->prtlen++;
break;
default:
if (cp->prtlen < prtinfo.linewidth) {
if ((cp->newline1)[cp->prtlen] == ' ') {
(cp->newline1)[cp->prtlen++] = c;
if (cp->prtlen > cp->prtlen1) cp->prtlen1 = cp->prtlen;
}
else if ((cp->newline2)[cp->prtlen] == ' ') {
(cp->newline2)[cp->prtlen++] = c;
if (cp->prtlen > cp->prtlen2) cp->prtlen2 = cp->prtlen;
}
else {
j = cp->prtlen;
prtwrite(&minus3, 0L, cp);
prtwrite(&minus2, 0L, cp);
cp->nextcc = '+';
cp->prtlen = j;
(cp->newline1)[cp->prtlen++] = c;
if (cp->prtlen > cp->prtlen1) cp->prtlen1 = cp->prtlen;
}
}
break;
}
}
return(0);
}
void prtline(unsigned char *s, cnr *cp)
{
GrafPtr gp;
char newpage;
int initskip, slen, leftoff, pglen;
int i;
unsigned char pbuff[12];
slen = strlen(s);
if (slen < 1) return; /* should never happen */
GetPort(&gp);
SetPort((GrafPtr)(cp->prtport));
newpage = 0;
if (cp->prtcc) {
leftoff = prtinfo.leftcc;
pglen = prtinfo.pagelencc;
}
else {
leftoff = prtinfo.left;
pglen = prtinfo.pagelength;
}
if (cp->prfileinit == 0) { /* initial call for a new file */
cp->prfileinit = 1;
cp->lineoffset = pglen;
newpage = 1;
initskip = 1;
cp->pgnum = 0;
maketitles(cp->tt1, cp->tt2, &(cp->tt1len), cp);
}
switch(s[0]) { /* interpret carriage control */
case '0':
cp->lineoffset += 2;
initskip = cp->lineoffset - pglen;
if (initskip > 0) newpage = 1;
break;
case '-':
cp->lineoffset += 3;
initskip = cp->lineoffset - pglen;
if (initskip > 0) newpage = 1;
break;
case '+':
break;
case '1':
initskip = 1;
newpage = 1;
break;
default:
cp->lineoffset ++;
initskip = cp->lineoffset - pglen;
if (initskip > 0) newpage = 1;
break;
}
if (newpage) {
if (cp->prpgopen) PrClosePage(cp->prtport);
cp->prpgopen = 0;
cp->pgnum++;
}
if (newpage && cp->pgnum >= cp->myFirst && cp->pgnum <= cp->myLast) {
PrOpenPage(cp->prtport, 0L);
cp->prpgopen = 1;
}
if (newpage) {
if (cp->prpgopen) {
TextFont(prtinfo.fontnum);
TextSize(prtinfo.pointsize);
PicComment(155, 0, 0L); /* line layout off */
}
cp->lineoffset = 0;
if (!(cp->prtcc)) {
memset(cp->tt1+cp->tt1len, 0x20, prtinfo.titlewidth-cp->tt1len);
if (cp->pgnum > 999) sprintf(pbuff, "Page%4d", cp->pgnum%10000);
else sprintf(pbuff, "Page %d", cp->pgnum);
i = strlen(pbuff);
memcpy(cp->tt1+prtinfo.titlewidth-i, pbuff, i);
i = prtinfo.titlewidth - cp->tt1len - i - strlen(cp->tt2);
if (i >= 4) memcpy(cp->tt1+cp->tt1len+(i/2), cp->tt2, strlen(cp->tt2));
if (cp->prpgopen) {
MoveTo(leftoff, cp->lineoffset*prtinfo.leading+prtinfo.top);
DrawText(cp->tt1, 0, prtinfo.titlewidth);
}
cp->lineoffset++;
if (i < 4) {
if (cp->prpgopen) {
MoveTo(leftoff, cp->lineoffset*prtinfo.leading+prtinfo.top);
DrawText(cp->tt2, 0, strlen(cp->tt2));
}
cp->lineoffset++;
}
cp->lineoffset += prtinfo.headmarg;
}
cp->lineoffset += initskip-1;
}
if (slen > 1) {
if (cp->prpgopen) {
MoveTo(leftoff, cp->lineoffset*prtinfo.leading+prtinfo.top);
DrawText(s+1, 0, slen-1);
}
}
SetPort(gp);
}
void maketitles(unsigned char *tt1, unsigned char *tt2, int *tt1len, cnr *cp)
{
short tlen;
static unsigned char * days[7] = {
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
static unsigned char * months[12] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
"Aug", "Sep", "Oct", "Nov", "Dec"};
static unsigned char am[3] = "AM";
static unsigned char pm[3] = "PM";
unsigned char * timeptr;
short hours;
unsigned long datesecs;
/* first line */
memset(tt1, 0x20, prtinfo.titlewidth);
tt1[prtinfo.titlewidth] = 0;
memcpy(tt1, "File: \"", 7);
tlen = strlen(cp->macFName+1);
if (tlen > prtinfo.titlewidth-16) tlen = prtinfo.titlewidth-16;
memcpy(tt1+7, cp->macFName+1, tlen);
if (tlen < prtinfo.titlewidth-16) {
tt1[tlen+7] = '"';
(*tt1len) = tlen+8;
}
else (*tt1len) = tlen+7;
/* second line */
Date2Secs(&(cp->wdate), &datesecs);
Secs2Date(datesecs, &(cp->wdate));
if (cp->wdate.hour < 12) timeptr = am;
else timeptr = pm;
if (cp->wdate.hour == 0) hours = 12;
else if (cp->wdate.hour > 12) hours = cp->wdate.hour - 12;
else hours = cp->wdate.hour;
sprintf(tt2, "Last Modified: %s, %s %d, %d %d:%02d:%02d %s",
days[cp->wdate.dayOfWeek-1], months[cp->wdate.month-1], cp->wdate.day,
cp->wdate.year, hours, cp->wdate.minute, cp->wdate.second, timeptr);
}